package tx.plus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;

public class ConnectionHandler implements InvocationHandler {
    private final static Logger LOGGER = LoggerFactory.getLogger("tx.plus.Connection");

    private final DataSource dataSource;
    private String username;
    private String password;
    private Connection target;

    private Boolean autoCommit;
    private Boolean autoCommitInit;
    private boolean autoCommitPromise;
    private boolean autoCommitPromiseSuc;
    private final static boolean DEFAULT_AUTO_COMMIT =true;


    ConnectionHandler(DataSource dataSource) {
       this.dataSource = dataSource;
    }

    ConnectionHandler(DataSource dataSource, String username, String password) {
        this.dataSource = dataSource;

        this.username = username;
        this.password = password;
    }
    private void connect() throws SQLException {
        // 其他的调用，需要连接
        target = username == null ? dataSource.getConnection()
                : dataSource.getConnection(username, password);
        LOGGER.info("getConnection");

        if(autoCommitPromise) {
            Boolean _autoCommit=autoCommit;
            boolean _autoCommitInit = target.getAutoCommit();
            LOGGER.debug("getAutoCommit - {}", _autoCommitInit);

            if(_autoCommitInit==DEFAULT_AUTO_COMMIT) {
                autoCommitPromiseSuc = true;
            }else {
                autoCommitInit = _autoCommitInit;
            }
            if(  _autoCommit != null && _autoCommit != _autoCommitInit ){
                // 保证一致
                LOGGER.info("setAutoCommit - {}", _autoCommit);
                target.setAutoCommit(_autoCommit);
            }

        }
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(this, args);
        }

        if (target == null) {
            if ("setAutoCommit".equals(method.getName())) {
                autoCommit = (Boolean) args[0];
                LOGGER.debug("lazy - {} - {}", method.getName(), autoCommit);
                return null;
            } else if ("getAutoCommit".equals(method.getName())) {
                Boolean _autoCommit=autoCommit;
                if(_autoCommit==null){
                    // 承诺行为
                    _autoCommit = DEFAULT_AUTO_COMMIT;
                    autoCommit=_autoCommit;
                    autoCommitPromise =true;
                }
                LOGGER.debug("lazy - {} -> {}", method.getName(), _autoCommit);
                return _autoCommit;
            } else if ("commit".equals(method.getName())
                    || "rollback".equals(method.getName())
                    || "close".equals(method.getName())) {
                LOGGER.info("ignore - {}", method.getName());
                return null;
            } else {

                connect();
                LOGGER.debug("{} - {}", method.getName(), args == null ? null : Arrays.asList(args));
                return method.invoke(target, args);
            }

        }else {

            if ("setAutoCommit".equals(method.getName())) {
                autoCommit = (Boolean) args[0];
            } else if ("close".equals(method.getName())) {
                if (autoCommitPromise &&!autoCommitPromiseSuc) {//关闭的时候 还原属性
                    LOGGER.info("setAutoCommit - {}", autoCommitInit);
                    target.setAutoCommit(autoCommitInit);
                }
            }
            LOGGER.debug("{} - {}", method.getName(), args == null ? null : Arrays.asList(args));
            return method.invoke(target, args);
        }


    }
}
